Do some anlysis
In this exercise we will work though a simple example of how to use GEE to obtain satellite imagery of a location, examine the topography, and run a simple normalized difference vegetation index for a dataset.
To begin, navigate to Google Earth Engine in a Chrome Browser. If you do not have Chrome you can install it from here. Your screen should appear like the one below

Each of the sections of the screen were described above in “Working with the Earth Engine API”, however, your screen will now show your information in the script manager. To start, click on the New button and create a new file. If prompted to create a repository, provide the name of a new repository to store your exercise script(s). Now, using the “Search places and datasets…” bar along the top of the page, type in Clarksville, TN and click on the appropriate result.

This will allow use to zoom in to Clarksville. We can use the zoom tools on the left or a double-click to refine the level of zoom. Once you have centered Clarksville, click on the Add a Marker icon in the upper left of the image to place a point (by left-clicking) near downtown.

Notice that you can also add lines, shape, and square/rectangle. With this marker placed, you should now see geometry imports available as well as a new var in the script box. By moving your mouse over the geometry box you can use the gear icon
you can change the name and color of the point. Rename the geometry to clarksville. Now that we have a location we can add a dataset. In the search box, type Sentinel 2 and select the import option next to the Sentinel-2 MSI: MultiSpectral Instrument, Level-1C from the rasters.
You will now see a new variable in your scripting window labeled as an ImageCollection. Essentially this means that the entire catalog of Sentinel 2 imagery is now available to this analysis. For more information on the sensor click the link for Sentinel 2. Here you will find information about he sensors availability range, provider, description, bands, spatial and temporal resolution, and image properties. This will be important later on when selecting the appropriate bands for analysis. Go ahead and rename this dataset sentinel2.
So now that we have a dataset to examine we can obtain information about our study site. If you were to run some datasets in the entirety you might receive an error statement in the console that says…
…this is due to an attempt to analyze an extremely large number of files in a dataset. If you need to examine global scale data you can contact Google to discuss a much larger quota. So in order to avoid such issues we are going to limit our search results.
To start, we will limit them based on geography. Because we only want images that intersect with our area of interest we can begin by setting the variable and providing a limit on its extent.
var image = ee.Image(sentinel2
.filterBounds(clarksville) // only include scenes that intersect with our point geometry
.filterDate("2019-01-01", "2019-10-30") // use to filter specific dates
.sort("CLOUD_COVERAGE_ASSESSMENT") // filter by cloudy pixel percentage
.first()); // select the least cloudy scene
In the script above:
- var image = ee.Image(sentinel2
- Identification of the data set
- .filterBounds(clarksville)
- Provides an intersection point for obtaining imagery
- .filterDate(“2019-01-01”, “2019-10-30”)
- Temporal limitation of the dataset for the first 10 months of 2019
- .sort(“CLOUD_COVERAGE_ASSESSMENT”)
- In the “Image Properties” of the Sentinel 2 link above, you will find that cloud coverage assessment refers to the percentage of could cover in the images. but using the sort() term we can organize them from smallest to largest.
- first()
- Selects the first image from the sorted, filtered list. Notice that script ends with a );. Remember it is javascript syntax to use a ; for the completion of a command. Additional we needed to end the open parenthese that began with ee.Image(.
Now that we have our filtered data, we can view the information in the console with print(image);. This identifies the image variable and provides information in the console tab. Information can be found regarding the number of available bands, cloud cover, etc.
In order to display the image we can set visualization parameters based on the information we want to obtain and the band combinations available in the data. For instance, if you want a “natural color” image (meaning as close to what you would see with your eyes from a plane) you would select the Red, Green, and Blue bands to display. If you wanted to examine vegetation, you would likely be interested in a false color composite with the Infrared, Red, and Green bands. For this example we will go ahead and make both.
var naturalcolor = {
bands: ["B4", "B3", "B2"],
min: 0,
max: 4000,
};
var falsecolor = {
bands: ["B8", "B4", "B3"],
min: 0,
max: 4000,
};
Now we have two variables, naturalcolor and falsecolor, we can use when displaying the imagery. To do that we want to add the information to the map using Map.addLayer():
Map.addLayer(image, naturalcolor, "Natural Color Composite");
Map.addLayer(image, falsecolor, "False Color Composite");
This added both the natural color and false color composite images to the active display. Using the options available under the layers box along the top of the map we can turn layers off and on, change the band combinations with the gear icon, and set the layer transparency with the slider bar.

Now that we have imagery of our area we can export that to a TIF file that can be used within other programs. To do this we will need to create a variable to be exported, provide some parameters, and create an export function that will run separately in the Tasks tab.
var exportRGB = image.visualize({
bands: ["B4", "B3", "B2"],
min: 0,
max: 4000,
});
Export.image.toDrive({
image: exportRGB,
scale: 10,
description: "clarksvilleRGB",
crs: "EPSG:4326",
});
Here we created a variable to export an RGB image. Next we used Export.image.t0Drive() to identify the variable (image), the scale of the pixels (10, found in the information on Sentinel), provide a description of the function, and finally the projection (EPSG:4326 = WGS84). When you run this script you can see there is a new task available.
Click run on the task and a new window will open prompting you to provide a location, file name, and additional resolution information.

These images will save in your Google Drive folder, so provide a file name and folder name. For resolution, because we learned that the spatial resolution of our bands was 10m we provided that information both in the scale and here in the resolution section. After a few minutes we will have a new raster file in our folder.
Try to repeat the process above using the USGS Landsat 8 Collection 1 Tier 1 TOA Reflectance. Remember to look at the description, bands, and image properties to include the appropriate information.
If we are interested in obtaining terrain information we can follow a similar process to the one above using a different sensor. The Shuttle Radar Topography Mission (SRTM Digital Elevation Data Version 4) from NASA-JPL provides near near-global scale, high-quality elevation data. Search for that dataset and import it as a variable named srtm. Now we can use Map.addLayer(srtm, {min:90, max:150}, 'DEM'); to add DEM information. The min and max values are the elevation range in meters.
Vegetation Analysis
One of the basic remote sensing analyses is a vegetation index called normalized differnce vegetation index (NDVI). It is calculated as a ration between red and near infrared bands with a range of -1 to 1. Where -1 is absence of vegetation and 1 is healthy green vegetation. This can quickly be calculated with the information we have already scripted.
To begin we need to create an equation and variables from the Sentinel data.
var NDVI = image.expression(
"(NIR - RED) / (NIR + RED)",
{
RED: image.select("B4"),
NIR: image.select("B8")
});
Map.addLayer(NDVI, {min: 0, max: 1}, "NDVI");
Remember that in Sentinel, Band 4 is the Red band and Band 8 is Near Infrared. Now we have a black and white image scaled with NDVI values.
If we want to determine the value of an individual pixel, we can use the inspector tab and use the crosshairs to click on an area of interest. Once you select a location and left-click you will see a series of graphs appear in the tab.
These graphs depict the pixel values of each band in the two image variables and the NDVI value of 0.251897. Click around the image on dark and light pixels and areas where you think you know the land cover to see if the results match your idea of the location (forest = high values, little/no vegetation = low values).
LS0tDQp0aXRsZTogQnJpZWYgSW50cm9kdWN0aW9uIHRvIEdvb2dsZSBFYXJ0aCBFbmdpbmUgPGJyPjxzbWFsbD5BZHZhbmNlZCBEYXRhIEFuYWx5dGljczwvc21hbGw+PC9icj4NCmF1dGhvcjogIkJJT0wgNTcwMCwgRmFsbCAyMDE5Ig0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIGhpZ2hsaWdodDogYnJlZXplZGFyaw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgcm93cy5wcmludDogMTANCiAgICB0aGVtZTogY29zbW8NCiAgICBiaWJsaW9ncmFwaHk6IGJpYmxpb2dyYXBoeS5iaWJ0ZXgNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogbm8NCiAgICAgIHNtb290aF9zY3JvbGw6IHllcw0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIHRvYzogeWVzDQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KZWRpdG9yX29wdGlvbnM6DQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCg0KaDEudGl0bGUgew0KICBmb250LXNpemU6IDQwcHg7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMjBweDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KPC9zdHlsZT4NCg0KIyBXaGF0IGlzIEdvb2dsZSBFYXJ0aCBFbmdpbmUNCg0KPHAgYWxpZ249ImNlbnRlciI+DQo8aWZyYW1lIHdpZHRoPSI3ODQiIGhlaWdodD0iNDQxIiBzcmM9Imh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL2VtYmVkL2dLR09lVEZIbktZIiBmcmFtZWJvcmRlcj0iMCIgYWxsb3c9ImFjY2VsZXJvbWV0ZXI7IGF1dG9wbGF5OyBlbmNyeXB0ZWQtbWVkaWE7IGd5cm9zY29wZTsgcGljdHVyZS1pbi1waWN0dXJlIiBhbGxvd2Z1bGxzY3JlZW4+PC9pZnJhbWU+DQo8L3A+DQoNCkdvb2dsZSBFYXJ0aCBFbmdpbmUgKEdFRSkgaXMgYSBjbG91ZC1iYXNlZCB0b29sIGZvciBzY2llbnRpZmljIGFuYWx5c2lzIGFuZCB2aXN1YWxpemF0aW9uIG9mIGdlb3NwYXRpYWwgZGF0YXNldHMsIGZvciBhY2FkZW1pYywgbm9uLXByb2ZpdCwgYnVzaW5lc3MgYW5kIGdvdmVybm1lbnQgdXNlcnMuDQoNCj4gIkdvb2dsZSBFYXJ0aCBFbmdpbmUgY29tYmluZXMgYSBtdWx0aS1wZXRhYnl0ZSBjYXRhbG9nIG9mIHNhdGVsbGl0ZSBpbWFnZXJ5IGFuZCBnZW9zcGF0aWFsIGRhdGFzZXRzIHdpdGggcGxhbmV0YXJ5LXNjYWxlIGFuYWx5c2lzIGNhcGFiaWxpdGllcyBhbmQgbWFrZXMgaXQgYXZhaWxhYmxlIGZvciBzY2llbnRpc3RzLCByZXNlYXJjaGVycywgYW5kIGRldmVsb3BlcnMgdG8gZGV0ZWN0IGNoYW5nZXMsIG1hcCB0cmVuZHMsIGFuZCBxdWFudGlmeSBkaWZmZXJlbmNlcyBvbiB0aGUgRWFydGgncyBzdXJmYWNlLiIgPHN1cD5bMV08L3N1cD4NCg0KV2hpbGUgR0VFIGlzIGN1cnJlbnRseSBmcmVlLCBpbmRpdmlkdWFscyBtdXN0IHJlcXVlc3QgYWNjZXNzIGZyb20gR29vZ2xlIGF0IFtodHRwczovL2VhcnRoZW5naW5lLmdvb2dsZS5jb20vc2lnbnVwL10oaHR0cHM6Ly9lYXJ0aGVuZ2luZS5nb29nbGUuY29tL3NpZ251cC8pLiBXaXRoIEdFRSwgR29vZ2xlIGhhcyBjcmVhdGVkIGEgcHVibGljIHJlcG9zaXRvcnkgb2YgZ2Vvc3BhdGlhbCBkYXRhIHRoYXQgaGFybmVzc2VzIHRoZSBwb3dlciBvZiBHb29nbGUncyBjbG91ZC1jb21wdXRpbmcgaW5mcmFzdHJ1Y3R1cmUgdG8gcmVtb3ZlIG9ic3RhY2xlcyB3aXRoIHJlZ2lvbmFsIHRvIHBsYW5ldGFyeSBzY2FsZSBhbmFseXNlcy4NCg0KSW4gYSB0cmFkaXRpb25hbCBzZW5zZSwgdGhlcmUgd2FzIGEgc3BlY2lmaWMgc2V0IHVwIHN0ZXBzIHJlcXVpcmVkIGluIG9yZGVyIHRvIGJlZ2luIGFueSByZW1vdGUgc2Vuc2luZyBhbmFseXNpcy4gSW4gZ2VuZXJhbCB0aG9zZSBzdGVwcyB3ZXJlOg0KDQoxLiBMb2NhdGUgaW1hZ2VyeSBzb3VyY2UNCjIuIElkZW50aWZ5IGFuYWx5c2lzIGxvY2F0aW9uIChwYXRoL3JvdywgbG9uZ2l0dWRlK2xhdGl0dWRlLCBldGMuKQ0KMy4gRmluZCBzY2VuZXMgd2l0aCBhcHByb3ByaWF0ZSBhdHRyaWJ1dGVzIChkYXRlLCBjbG91ZCBjb3ZlciwgZXRjLikNCjQuIERvd25sb2FkIG9yIHJlcXVlc3Qgc2NlbmUocykNCjUuIENvbXBpbGUgYmFuZHMgaW50byBzaW5nbGUgaW1hZ2UNCg0KVGhpcyBwcm9jZXNzIG9mIG9idGFpbmluZyBkYXRhIGNvdWxkIHRha2UgYW55d2hlcmUgZnJvbSBzZXZlcmFsIG1pbnV0ZXMgdG8gc2V2ZXJhbCBob3VycyBkZXBlbmRpbmcgb24gdGhlIG5hdHVyZSBvZiB0aGUgZGF0YSBhbmQgdGhlIHVzZXJzIGV4cGVyaWVuY2Ugd2l0aCB0aGUgc29mdHdhcmUuIFdoYXQgbWFrZXMgR0VFIHVuaXF1ZSBpcyB0aGUgZm9jdXMgb24gYW5hbHlzaXMgYnkgcmVtb3ZpbmcgdGhlIHN0ZXBzIHJlcXVpcmVkIHRvIGNhdGFsb2csIG9yZ2FuaXplLCBhbmQgcHJvY2VzcyByZW1vdGVseSBzZW5zZWQgaW1hZ2VyeS4gDQoNCiMgRGF0YSBDYXRhbG9nIA0KR0VFIGNvbnRhaW5zIG1vcmUgdGhhbiAyOSBwZXRhYnl0ZXMgKDEgcGV0YWJ5dGUgPSAgMSBtaWxsaW9uIGdpZ2FieXRlcykgb2YgY2F0YWxvZ2VkIHJhc3RlciBhbmQgdmVjdG9yIGRhdGFzZXRzLiBUaGlzIGRhdGEgYXJlIGF1dG8tdXBkYXRlZCBkYWlseSBieSB0aGUgR29vZ2xlIEVhcnRoIEVuZ2luZSB0ZWFtIGFuZCBuZXcgZGF0YXNldHMgYXJlIGJlaW5nIGFkZGVkIG1vbnRobHkuIElmIHlvdSBmaW5kIHRoYXQgYSBkYXRhc2V0IHlvdSB1c2UgaXMgbm90IGN1cnJlbnRseSBjb250YWluZWQgd2l0aGluIHRoZSBjYXRhbG9nIHlvdSBjYW4gW3N1Z2dlc3QgYSBuZXcgZGF0YXNldF0oaHR0cHM6Ly9pc3N1ZXRyYWNrZXIuZ29vZ2xlLmNvbS9pc3N1ZXMvbmV3P2NvbXBvbmVudD0xODQ0MjYmdGVtcGxhdGU9NzE5NTAzKSBiZSBhZGRlZCBieSB0aGUgR0VFIHRlYW0uDQoNCjxwIGFsaWduPSJjZW50ZXIiPg0KDQohW10oLi9JbWFnZXMvR0VfQ2F0YWxvZy5wbmcgIkVhcnRoIEVuZ2luZSBEYXRhIENhdGFsb2ciKQ0KDQo8L3A+DQoNCldpdGggR0VFLCBHb29nbGUgaGFzIHByb3ZpZGVkIHRoZSB0b29scyBhbmQgYXBwbGljYXRpb24gcHJvZ3JhbW1pbmcgaW50ZXJmYWNlIChBUEkpIG5lY2Vzc2FyeSB0byBxdWlja2x5IG1vdmUgZnJvbSBvYnRhaW5pbmcgYSBkYXRhc2V0IHRvIGV4cGxvcmF0b3J5IGFuYWx5c2lzLiBBbGwgb2YgdGhlc2UgYW5hbHlzZXMgYXJlIHJ1biBvbiBHb29nbGUgc2VydmVycyB3aGVyZSB0aGUgZGF0YSBpcyBzdG9yZWQgYWxsb3dpbmcgZm9yIHNwZWVkIGFuZCBwcm9jZXNzaW5nIHBvd2VyIHdlbGwgYmV5b25kIHRoYXQgb2YgYSBzaW5nbGUgY29tcHV0ZXIuIEFkZGl0aW9uYWxseSwgdGhyb3VnaCB0aGUgdXNlIG9mIGphdmFzY3JpcHQgb3IgcHl0aG9uLCBzY2llbnRpc3RzIGNhbiBjcmVhdGUgcmVwZWF0YWJsZSBhbmFseXNlcyBhbmQgc2hhcmUgdGhvc2Ugd2l0aCBvdGhlciB1c2VycyBieSBzaW1wbHkgc2hhcmluZyBhIHNpbmdsZSB3ZWIgYWRkcmVzcy4NCg0KIyBXb3JraW5nIGluIHRoZSBFYXJ0aCBFbmdpbmUgQVBJDQoNCldvcmtpbmcgd2l0aGluIHRoZSBHb29nbGUgQ2hyb21lIGJyb3dzZXIsIEdFRSBwcm92aWRlcyBhbiBBUEkgdGhhdCBhbGxvd3MgeW91IHRvIHNlYXJjaCBmb3IgZGF0YXNldHMsIHZpc3VhbGl6ZSB0aGUgZGF0YSwgZGV2ZWxvcCBjb2RlLCBleGFtaW5lIHRoZSByZXN1bHRzIG9mIHlvdXIgYW5hbHlzZXMsIGFuZCBzYXZlIHlvdXIgd29yayB3aXRoaW4gYSByZXBvc2l0b3J5Lg0KDQo8cCBhbGlnbj0iY2VudGVyIj4NCg0KIVtdKGh0dHBzOi8vZ2l0aHViLmNvbS9nZW9zcGF0aWFsZWNvL0dFQVJTL3Jhdy9tYXN0ZXIvZ2VlX2VkaXRvci5wbmcgIkdFRSBFZGl0b3IiKQ0KDQo8L3A+DQoNCjEuIEVkaXRvciBQYW5lbA0KICAgKiBVc2VkIGZvciB3cml0aW5nIGFuZCBlZGl0aW5nIHlvdXIgSmF2YXNjcmlwdCBjb2RlDQoyLiBSaWdodCBQYW5lbA0KICAgKiBDb25zb2xlIHRhYiBmb3Igb3V0cHV0IGluZm9ybWF0aW9uDQogICAqIEluc3BlY3RvciB0YWIgZm9yIHF1ZXJ5aW5nIHJlc3VsdHMNCiAgICogVGFza3MgdGFiIGZvciBtYW5hZ2luZyBleGVjdXRlZCB0YXNrcw0KMy4gTGVmdCBQYW5lbA0KICAgKiBTY3JpcHRzIHRhYiBmb3IgbWFuYWdpbmcgeW91ciBwcm9ncmFtbWluZyBzY3JpcHRzDQogICAqIERvY3MgdGFiIGZvciBhY2Nlc3NpbmcgZG9jdW1lbnRhdGlvbiBvZiBFYXJ0aCBFbmdpbmUgb2JqZWN0cyBhbmQgbWV0aG9kcywgYXMgd2VsbCBhcyBhIGZldyBzcGVjaWZpYyB0byB0aGUgQ29kZSBFZGl0b3IgYXBwbGljYXRpb24NCiAgICogQXNzZXRzIHRhYiBmb3IgbWFuYWdpbmcgYXNzZXRzIHRoYXQgeW91IHVwbG9hZA0KNC4gSW50ZXJhY3RpdmUgTWFwDQogICAqIEZvciB2aXN1YWxpemluZyBtYXAgbGF5ZXIgb3V0cHV0DQo1LiBTZWFyY2ggQmFyDQogICAqIEZvciBmaW5kaW5nIGRhdGFzZXRzIGFuZCBwbGFjZXMgb2YgaW50ZXJlc3QNCjYuIEhlbHAgTWVudQ0KICAgKiBVc2VyIGd1aWRlDQogICAqIEhlbHAgZm9ydW0NCiAgICogU2hvcnRjdXRzDQogICAqIEZlYXR1cmUgVG91cg0KICAgKiBGZWVkYmFjaw0KICAgKiBTdWdnZXN0IGEgZGF0YXNldA0KDQojIERvIHNvbWUgYW5seXNpcw0KDQpJbiB0aGlzIGV4ZXJjaXNlIHdlIHdpbGwgd29yayB0aG91Z2ggYSBzaW1wbGUgZXhhbXBsZSBvZiBob3cgdG8gdXNlIEdFRSB0byBvYnRhaW4gc2F0ZWxsaXRlIGltYWdlcnkgb2YgYSBsb2NhdGlvbiwgZXhhbWluZSB0aGUgdG9wb2dyYXBoeSwgYW5kIHJ1biBhIHNpbXBsZSBub3JtYWxpemVkIGRpZmZlcmVuY2UgdmVnZXRhdGlvbiBpbmRleCBmb3IgYSBkYXRhc2V0Lg0KDQpUbyBiZWdpbiwgbmF2aWdhdGUgdG8gW0dvb2dsZSBFYXJ0aCBFbmdpbmVdKGh0dHBzOi8vY29kZS5lYXJ0aGVuZ2luZS5nb29nbGUuY29tLykgaW4gYSBDaHJvbWUgQnJvd3Nlci4gSWYgeW91IGRvIG5vdCBoYXZlIENocm9tZSB5b3UgY2FuIGluc3RhbGwgaXQgZnJvbSBbaGVyZV0oaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS9jaHJvbWUvKS4gWW91ciBzY3JlZW4gc2hvdWxkIGFwcGVhciBsaWtlIHRoZSBvbmUgYmVsb3cNCg0KPHAgYWxpZ249ImNlbnRlciI+DQoNCiFbXSguL0ltYWdlcy9HRUUucG5nICJHb29nbGUgRWFydGggRW5naW5lIikNCg0KPC9wPg0KDQpFYWNoIG9mIHRoZSBzZWN0aW9ucyBvZiB0aGUgc2NyZWVuIHdlcmUgZGVzY3JpYmVkIGFib3ZlIGluICJXb3JraW5nIHdpdGggdGhlIEVhcnRoIEVuZ2luZSBBUEkiLCBob3dldmVyLCB5b3VyIHNjcmVlbiB3aWxsIG5vdyBzaG93IHlvdXIgaW5mb3JtYXRpb24gaW4gdGhlIHNjcmlwdCBtYW5hZ2VyLiBUbyBzdGFydCwgY2xpY2sgb24gdGhlICoqTmV3KiogYnV0dG9uIGFuZCBjcmVhdGUgYSBuZXcgZmlsZS4gSWYgcHJvbXB0ZWQgdG8gY3JlYXRlIGEgcmVwb3NpdG9yeSwgcHJvdmlkZSB0aGUgbmFtZSBvZiBhIG5ldyByZXBvc2l0b3J5IHRvIHN0b3JlIHlvdXIgZXhlcmNpc2Ugc2NyaXB0KHMpLiBOb3csIHVzaW5nIHRoZSAqIlNlYXJjaCBwbGFjZXMgYW5kIGRhdGFzZXRzLi4uIiogYmFyIGFsb25nIHRoZSB0b3Agb2YgdGhlIHBhZ2UsIHR5cGUgaW4gQ2xhcmtzdmlsbGUsIFROIGFuZCBjbGljayBvbiB0aGUgYXBwcm9wcmlhdGUgcmVzdWx0Lg0KDQo8cCBhbGlnbj0iY2VudGVyIj4NCg0KIVtdKC4vSW1hZ2VzL0NsYXJrc3ZpbGxlX1NlYXJjaC5wbmcgIlVzaW5nIHRoZSBzZWFyY2ggYmFyIikNCg0KPC9wPg0KDQpUaGlzIHdpbGwgYWxsb3cgdXNlIHRvIHpvb20gaW4gdG8gQ2xhcmtzdmlsbGUuIFdlIGNhbiB1c2UgdGhlIHpvb20gdG9vbHMgb24gdGhlIGxlZnQgb3IgYSBkb3VibGUtY2xpY2sgdG8gcmVmaW5lIHRoZSBsZXZlbCBvZiB6b29tLiBPbmNlIHlvdSBoYXZlIGNlbnRlcmVkIENsYXJrc3ZpbGxlLCBjbGljayBvbiB0aGUgKipBZGQgYSBNYXJrZXIqKiBpY29uIGluIHRoZSB1cHBlciBsZWZ0IG9mIHRoZSBpbWFnZSB0byBwbGFjZSBhIHBvaW50IChieSBsZWZ0LWNsaWNraW5nKSBuZWFyIGRvd250b3duLiANCg0KPHAgYWxpZ249ImNlbnRlciI+DQoNCiFbXSguL0ltYWdlcy9NYXJrZXJfSWNvbi5wbmcgIkFkZCBhIG1hcmtlciIpDQoNCjwvcD4NCk5vdGljZSB0aGF0IHlvdSBjYW4gYWxzbyBhZGQgbGluZXMsIHNoYXBlLCBhbmQgc3F1YXJlL3JlY3RhbmdsZS4gV2l0aCB0aGlzIG1hcmtlciBwbGFjZWQsIHlvdSBzaG91bGQgbm93IHNlZSAqKmdlb21ldHJ5IGltcG9ydHMqKiBhdmFpbGFibGUgYXMgd2VsbCBhcyBhIG5ldyAqdmFyKiBpbiB0aGUgc2NyaXB0IGJveC4gQnkgbW92aW5nIHlvdXIgbW91c2Ugb3ZlciB0aGUgKmdlb21ldHJ5KiBib3ggeW91IGNhbiB1c2UgdGhlIGdlYXIgaWNvbiAhW10oLi9JbWFnZXMvR2Vhcl9JY29uLnBuZyAiR2VhciBJY29uIikgeW91IGNhbiBjaGFuZ2UgdGhlIG5hbWUgYW5kIGNvbG9yIG9mIHRoZSBwb2ludC4gUmVuYW1lIHRoZSBnZW9tZXRyeSB0byBjbGFya3N2aWxsZS4gTm93IHRoYXQgd2UgaGF2ZSBhIGxvY2F0aW9uIHdlIGNhbiBhZGQgYSBkYXRhc2V0LiBJbiB0aGUgc2VhcmNoIGJveCwgdHlwZSAqKlNlbnRpbmVsIDIqKiBhbmQgc2VsZWN0IHRoZSBpbXBvcnQgb3B0aW9uIG5leHQgdG8gdGhlICpTZW50aW5lbC0yIE1TSTogTXVsdGlTcGVjdHJhbCBJbnN0cnVtZW50LCBMZXZlbC0xQyogZnJvbSB0aGUgcmFzdGVycy4gDQoNCjxwIGFsaWduPSJjZW50ZXIiPg0KDQohW10oLi9JbWFnZXMvSW1wb3J0X1NlbnRpbmVsLnBuZyAiSW1wb3J0aW5nIGEgbmV3IGRhdGFzZXQiKQ0KPC9wPg0KDQpZb3Ugd2lsbCBub3cgc2VlIGEgbmV3IHZhcmlhYmxlIGluIHlvdXIgc2NyaXB0aW5nIHdpbmRvdyBsYWJlbGVkIGFzIGFuICoqSW1hZ2VDb2xsZWN0aW9uKiouIEVzc2VudGlhbGx5IHRoaXMgbWVhbnMgdGhhdCB0aGUgZW50aXJlIGNhdGFsb2cgb2YgKlNlbnRpbmVsIDIqIGltYWdlcnkgaXMgbm93IGF2YWlsYWJsZSB0byB0aGlzIGFuYWx5c2lzLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiBvbiB0aGUgc2Vuc29yIGNsaWNrIHRoZSBsaW5rIGZvciBbU2VudGluZWwgMl0oaHR0cHM6Ly9kZXZlbG9wZXJzLmdvb2dsZS5jb20vZWFydGgtZW5naW5lL2RhdGFzZXRzL2NhdGFsb2cvQ09QRVJOSUNVU19TMikuIEhlcmUgeW91IHdpbGwgZmluZCBpbmZvcm1hdGlvbiBhYm91dCBoZSBzZW5zb3JzIGF2YWlsYWJpbGl0eSByYW5nZSwgcHJvdmlkZXIsIGRlc2NyaXB0aW9uLCBiYW5kcywgc3BhdGlhbCBhbmQgdGVtcG9yYWwgcmVzb2x1dGlvbiwgYW5kIGltYWdlIHByb3BlcnRpZXMuIFRoaXMgd2lsbCBiZSBpbXBvcnRhbnQgbGF0ZXIgb24gd2hlbiBzZWxlY3RpbmcgdGhlIGFwcHJvcHJpYXRlIGJhbmRzIGZvciBhbmFseXNpcy4gR28gYWhlYWQgYW5kIHJlbmFtZSB0aGlzIGRhdGFzZXQgKnNlbnRpbmVsMiouDQoNClNvIG5vdyB0aGF0IHdlIGhhdmUgYSBkYXRhc2V0IHRvIGV4YW1pbmUgd2UgY2FuIG9idGFpbiBpbmZvcm1hdGlvbiBhYm91dCBvdXIgc3R1ZHkgc2l0ZS4gSWYgeW91IHdlcmUgdG8gcnVuIHNvbWUgZGF0YXNldHMgaW4gdGhlIGVudGlyZXR5IHlvdSBtaWdodCByZWNlaXZlIGFuIGVycm9yIHN0YXRlbWVudCBpbiB0aGUgY29uc29sZSB0aGF0IHNheXMuLi4NCg0KPHAgYWxpZ249ImNlbnRlciI+DQoNCiFbXSguL0ltYWdlcy9wcmludF9lcnJvci5wbmcgIkVycm9yIG1lc3NhZ2UiKQ0KPC9wPg0KDQouLi50aGlzIGlzIGR1ZSB0byBhbiBhdHRlbXB0IHRvIGFuYWx5emUgYW4gZXh0cmVtZWx5IGxhcmdlIG51bWJlciBvZiBmaWxlcyBpbiBhIGRhdGFzZXQuIElmIHlvdSBuZWVkIHRvIGV4YW1pbmUgZ2xvYmFsIHNjYWxlIGRhdGEgeW91IGNhbiBjb250YWN0IEdvb2dsZSB0byBkaXNjdXNzIGEgbXVjaCBsYXJnZXIgcXVvdGEuIFNvIGluIG9yZGVyIHRvIGF2b2lkIHN1Y2ggaXNzdWVzIHdlIGFyZSBnb2luZyB0byBsaW1pdCBvdXIgc2VhcmNoIHJlc3VsdHMuDQoNClRvIHN0YXJ0LCB3ZSB3aWxsIGxpbWl0IHRoZW0gYmFzZWQgb24gZ2VvZ3JhcGh5LiBCZWNhdXNlIHdlIG9ubHkgd2FudCBpbWFnZXMgdGhhdCBpbnRlcnNlY3Qgd2l0aCBvdXIgYXJlYSBvZiBpbnRlcmVzdCB3ZSBjYW4gYmVnaW4gYnkgc2V0dGluZyB0aGUgdmFyaWFibGUgYW5kIHByb3ZpZGluZyBhIGxpbWl0IG9uIGl0cyBleHRlbnQuDQoNCmBgYA0KdmFyIGltYWdlID0gZWUuSW1hZ2Uoc2VudGluZWwyDQogIC5maWx0ZXJCb3VuZHMoY2xhcmtzdmlsbGUpIC8vIG9ubHkgaW5jbHVkZSBzY2VuZXMgdGhhdCBpbnRlcnNlY3Qgd2l0aCBvdXIgcG9pbnQgZ2VvbWV0cnkNCiAgLmZpbHRlckRhdGUoIjIwMTktMDEtMDEiLCAiMjAxOS0xMC0zMCIpIC8vIHVzZSB0byBmaWx0ZXIgc3BlY2lmaWMgZGF0ZXMNCiAgLnNvcnQoIkNMT1VEX0NPVkVSQUdFX0FTU0VTU01FTlQiKSAvLyBmaWx0ZXIgYnkgY2xvdWR5IHBpeGVsIHBlcmNlbnRhZ2UNCiAgLmZpcnN0KCkpOyAvLyBzZWxlY3QgdGhlIGxlYXN0IGNsb3VkeSBzY2VuZSANCmBgYA0KDQpJbiB0aGUgc2NyaXB0IGFib3ZlOg0KDQoxLiB2YXIgaW1hZ2UgPSBlZS5JbWFnZShzZW50aW5lbDINCiAgICAqIElkZW50aWZpY2F0aW9uIG9mIHRoZSBkYXRhIHNldA0KMi4gLmZpbHRlckJvdW5kcyhjbGFya3N2aWxsZSkNCiAgICAqIFByb3ZpZGVzIGFuIGludGVyc2VjdGlvbiBwb2ludCBmb3Igb2J0YWluaW5nIGltYWdlcnkNCjMuIC5maWx0ZXJEYXRlKCIyMDE5LTAxLTAxIiwgIjIwMTktMTAtMzAiKQ0KICAgICogVGVtcG9yYWwgbGltaXRhdGlvbiBvZiB0aGUgZGF0YXNldCBmb3IgdGhlIGZpcnN0IDEwIG1vbnRocyBvZiAyMDE5DQo0LiAuc29ydCgiQ0xPVURfQ09WRVJBR0VfQVNTRVNTTUVOVCIpDQogICAgKiBJbiB0aGUgIkltYWdlIFByb3BlcnRpZXMiIG9mIHRoZSAqU2VudGluZWwgMiogbGluayBhYm92ZSwgeW91IHdpbGwgZmluZCB0aGF0IGNsb3VkIGNvdmVyYWdlIGFzc2Vzc21lbnQgcmVmZXJzIHRvIHRoZSBwZXJjZW50YWdlIG9mIGNvdWxkIGNvdmVyIGluIHRoZSBpbWFnZXMuIGJ1dCB1c2luZyB0aGUgc29ydCgpIHRlcm0gd2UgY2FuIG9yZ2FuaXplIHRoZW0gZnJvbSBzbWFsbGVzdCB0byBsYXJnZXN0Lg0KNS4gZmlyc3QoKQ0KICAgICogU2VsZWN0cyB0aGUgZmlyc3QgaW1hZ2UgZnJvbSB0aGUgc29ydGVkLCBmaWx0ZXJlZCBsaXN0LiBOb3RpY2UgdGhhdCBzY3JpcHQgZW5kcyB3aXRoIGEgKTsuIFJlbWVtYmVyIGl0IGlzIGphdmFzY3JpcHQgc3ludGF4IHRvIHVzZSBhIDsgZm9yIHRoZSBjb21wbGV0aW9uIG9mIGEgY29tbWFuZC4gQWRkaXRpb25hbCB3ZSBuZWVkZWQgdG8gZW5kIHRoZSBvcGVuIHBhcmVudGhlc2UgdGhhdCBiZWdhbiB3aXRoIGVlLkltYWdlKC4NCg0KTm93IHRoYXQgd2UgaGF2ZSBvdXIgZmlsdGVyZWQgZGF0YSwgd2UgY2FuIHZpZXcgdGhlIGluZm9ybWF0aW9uIGluIHRoZSBjb25zb2xlIHdpdGggYGBgcHJpbnQoaW1hZ2UpO2BgYC4gVGhpcyBpZGVudGlmaWVzIHRoZSAqKmltYWdlKiogdmFyaWFibGUgYW5kIHByb3ZpZGVzIGluZm9ybWF0aW9uIGluIHRoZSBjb25zb2xlIHRhYi4gSW5mb3JtYXRpb24gY2FuIGJlIGZvdW5kIHJlZ2FyZGluZyB0aGUgbnVtYmVyIG9mIGF2YWlsYWJsZSBiYW5kcywgY2xvdWQgY292ZXIsIGV0Yy4NCg0KPHAgYWxpZ249ImNlbnRlciI+DQoNCiFbXSguL0ltYWdlcy9pbWFnZV9jb25zb2xlLnBuZyAiQ29uc29sZSIpDQo8L3A+DQoNCkluIG9yZGVyIHRvIGRpc3BsYXkgdGhlIGltYWdlIHdlIGNhbiBzZXQgdmlzdWFsaXphdGlvbiBwYXJhbWV0ZXJzIGJhc2VkIG9uIHRoZSBpbmZvcm1hdGlvbiB3ZSB3YW50IHRvIG9idGFpbiBhbmQgdGhlIGJhbmQgY29tYmluYXRpb25zIGF2YWlsYWJsZSBpbiB0aGUgZGF0YS4gRm9yIGluc3RhbmNlLCBpZiB5b3Ugd2FudCBhICJuYXR1cmFsIGNvbG9yIiBpbWFnZSAobWVhbmluZyBhcyBjbG9zZSB0byB3aGF0IHlvdSB3b3VsZCBzZWUgd2l0aCB5b3VyIGV5ZXMgZnJvbSBhIHBsYW5lKSB5b3Ugd291bGQgc2VsZWN0IHRoZSBSZWQsIEdyZWVuLCBhbmQgQmx1ZSBiYW5kcyB0byBkaXNwbGF5LiBJZiB5b3Ugd2FudGVkIHRvIGV4YW1pbmUgdmVnZXRhdGlvbiwgeW91IHdvdWxkIGxpa2VseSBiZSBpbnRlcmVzdGVkIGluIGEgZmFsc2UgY29sb3IgY29tcG9zaXRlIHdpdGggdGhlIEluZnJhcmVkLCBSZWQsIGFuZCBHcmVlbiBiYW5kcy4gRm9yIHRoaXMgZXhhbXBsZSB3ZSB3aWxsIGdvIGFoZWFkIGFuZCBtYWtlIGJvdGguDQoNCmBgYA0KdmFyIG5hdHVyYWxjb2xvciA9IHsNCiAgYmFuZHM6IFsiQjQiLCAiQjMiLCAiQjIiXSwNCiAgbWluOiAwLA0KICBtYXg6IDQwMDAsDQp9Ow0KDQp2YXIgZmFsc2Vjb2xvciA9IHsNCiAgYmFuZHM6IFsiQjgiLCAiQjQiLCAiQjMiXSwNCiAgbWluOiAwLA0KICBtYXg6IDQwMDAsDQp9Ow0KYGBgDQpOb3cgd2UgaGF2ZSB0d28gdmFyaWFibGVzLCAqbmF0dXJhbGNvbG9yKiBhbmQgKmZhbHNlY29sb3IqLCB3ZSBjYW4gdXNlIHdoZW4gZGlzcGxheWluZyB0aGUgaW1hZ2VyeS4gVG8gZG8gdGhhdCB3ZSB3YW50IHRvIGFkZCB0aGUgaW5mb3JtYXRpb24gdG8gdGhlIG1hcCB1c2luZyBNYXAuYWRkTGF5ZXIoKToNCg0KYGBgDQpNYXAuYWRkTGF5ZXIoaW1hZ2UsIG5hdHVyYWxjb2xvciwgIk5hdHVyYWwgQ29sb3IgQ29tcG9zaXRlIik7DQpNYXAuYWRkTGF5ZXIoaW1hZ2UsIGZhbHNlY29sb3IsICJGYWxzZSBDb2xvciBDb21wb3NpdGUiKTsNCmBgYA0KDQpUaGlzIGFkZGVkIGJvdGggdGhlIG5hdHVyYWwgY29sb3IgYW5kIGZhbHNlIGNvbG9yIGNvbXBvc2l0ZSBpbWFnZXMgdG8gdGhlIGFjdGl2ZSBkaXNwbGF5LiBVc2luZyB0aGUgb3B0aW9ucyBhdmFpbGFibGUgdW5kZXIgdGhlICoqbGF5ZXJzKiogYm94IGFsb25nIHRoZSB0b3Agb2YgdGhlIG1hcCB3ZSBjYW4gdHVybiBsYXllcnMgb2ZmIGFuZCBvbiwgY2hhbmdlIHRoZSBiYW5kIGNvbWJpbmF0aW9ucyB3aXRoIHRoZSBnZWFyIGljb24sIGFuZCBzZXQgdGhlIGxheWVyIHRyYW5zcGFyZW5jeSB3aXRoIHRoZSBzbGlkZXIgYmFyLg0KDQo8cCBhbGlnbj0iY2VudGVyIj4NCg0KIVtdKC4vSW1hZ2VzL21hcF92aWV3LnBuZyAiTWFwIFZpZXciKQ0KDQpOb3cgdGhhdCB3ZSBoYXZlIGltYWdlcnkgb2Ygb3VyIGFyZWEgd2UgY2FuIGV4cG9ydCB0aGF0IHRvIGEgVElGIGZpbGUgdGhhdCBjYW4gYmUgdXNlZCB3aXRoaW4gb3RoZXIgcHJvZ3JhbXMuIFRvIGRvIHRoaXMgd2Ugd2lsbCBuZWVkIHRvIGNyZWF0ZSBhIHZhcmlhYmxlIHRvIGJlIGV4cG9ydGVkLCBwcm92aWRlIHNvbWUgcGFyYW1ldGVycywgYW5kIGNyZWF0ZSBhbiBleHBvcnQgZnVuY3Rpb24gdGhhdCB3aWxsIHJ1biBzZXBhcmF0ZWx5IGluIHRoZSAqKlRhc2tzKiogdGFiLg0KDQpgYGANCnZhciBleHBvcnRSR0IgPSBpbWFnZS52aXN1YWxpemUoew0KICBiYW5kczogWyJCNCIsICJCMyIsICJCMiJdLA0KICBtaW46IDAsDQogIG1heDogNDAwMCwNCn0pOw0KDQpFeHBvcnQuaW1hZ2UudG9Ecml2ZSh7DQogIGltYWdlOiBleHBvcnRSR0IsDQogIHNjYWxlOiAxMCwNCiAgZGVzY3JpcHRpb246ICJjbGFya3N2aWxsZVJHQiIsDQogIGNyczogIkVQU0c6NDMyNiIsDQp9KTsNCmBgYA0KSGVyZSB3ZSBjcmVhdGVkIGEgdmFyaWFibGUgdG8gZXhwb3J0IGFuIFJHQiBpbWFnZS4gTmV4dCB3ZSB1c2VkIEV4cG9ydC5pbWFnZS50MERyaXZlKCkgdG8gaWRlbnRpZnkgdGhlIHZhcmlhYmxlIChpbWFnZSksIHRoZSBzY2FsZSBvZiB0aGUgcGl4ZWxzICgxMCwgZm91bmQgaW4gdGhlIGluZm9ybWF0aW9uIG9uIFNlbnRpbmVsKSwgcHJvdmlkZSBhIGRlc2NyaXB0aW9uIG9mIHRoZSBmdW5jdGlvbiwgYW5kIGZpbmFsbHkgdGhlIHByb2plY3Rpb24gKEVQU0c6NDMyNiA9IFdHUzg0KS4gV2hlbiB5b3UgcnVuIHRoaXMgc2NyaXB0IHlvdSBjYW4gc2VlIHRoZXJlIGlzIGEgbmV3IHRhc2sgYXZhaWxhYmxlLg0KDQo8cCBhbGlnbj0iY2VudGVyIj4NCg0KIVtdKC4vSW1hZ2VzL1Rhc2tfSW1hZ2VfRXhwb3J0LnBuZyAiVGFza3MgVGFiIikNCjwvcD4NCkNsaWNrIHJ1biBvbiB0aGUgdGFzayBhbmQgYSBuZXcgd2luZG93IHdpbGwgb3BlbiBwcm9tcHRpbmcgeW91IHRvIHByb3ZpZGUgYSBsb2NhdGlvbiwgZmlsZSBuYW1lLCBhbmQgYWRkaXRpb25hbCByZXNvbHV0aW9uIGluZm9ybWF0aW9uLg0KDQo8cCBhbGlnbj0iY2VudGVyIj4NCg0KIVtdKC4vSW1hZ2VzL0V4cG9ydF9PcHRpb25zLnBuZyAiRXhwb3J0IE9wdGlvbnMgTWVudSIpDQoNCjwvcD4NCg0KVGhlc2UgaW1hZ2VzIHdpbGwgc2F2ZSBpbiB5b3VyIEdvb2dsZSBEcml2ZSBmb2xkZXIsIHNvIHByb3ZpZGUgYSBmaWxlIG5hbWUgYW5kIGZvbGRlciBuYW1lLiBGb3IgcmVzb2x1dGlvbiwgYmVjYXVzZSB3ZSBsZWFybmVkIHRoYXQgdGhlIHNwYXRpYWwgcmVzb2x1dGlvbiBvZiBvdXIgYmFuZHMgd2FzIDEwbSB3ZSBwcm92aWRlZCB0aGF0IGluZm9ybWF0aW9uIGJvdGggaW4gdGhlIHNjYWxlIGFuZCBoZXJlIGluIHRoZSByZXNvbHV0aW9uIHNlY3Rpb24uIEFmdGVyIGEgZmV3IG1pbnV0ZXMgd2Ugd2lsbCBoYXZlIGEgbmV3IHJhc3RlciBmaWxlIGluIG91ciBmb2xkZXIuDQoNCj4gVHJ5IHRvIHJlcGVhdCB0aGUgcHJvY2VzcyBhYm92ZSB1c2luZyB0aGUgVVNHUyBMYW5kc2F0IDggQ29sbGVjdGlvbiAxIFRpZXIgMSBUT0EgUmVmbGVjdGFuY2UuIFJlbWVtYmVyIHRvIGxvb2sgYXQgdGhlIGRlc2NyaXB0aW9uLCBiYW5kcywgYW5kIGltYWdlIHByb3BlcnRpZXMgdG8gaW5jbHVkZSB0aGUgYXBwcm9wcmlhdGUgaW5mb3JtYXRpb24uDQoNCklmIHdlIGFyZSBpbnRlcmVzdGVkIGluIG9idGFpbmluZyB0ZXJyYWluIGluZm9ybWF0aW9uIHdlIGNhbiBmb2xsb3cgYSBzaW1pbGFyIHByb2Nlc3MgdG8gdGhlIG9uZSBhYm92ZSB1c2luZyBhIGRpZmZlcmVudCBzZW5zb3IuIFRoZSAqU2h1dHRsZSBSYWRhciBUb3BvZ3JhcGh5IE1pc3Npb24qIChTUlRNIERpZ2l0YWwgRWxldmF0aW9uIERhdGEgVmVyc2lvbiA0KSBmcm9tIE5BU0EtSlBMIHByb3ZpZGVzIG5lYXIgbmVhci1nbG9iYWwgc2NhbGUsIGhpZ2gtcXVhbGl0eSBlbGV2YXRpb24gZGF0YS4gU2VhcmNoIGZvciB0aGF0IGRhdGFzZXQgYW5kIGltcG9ydCBpdCBhcyBhIHZhcmlhYmxlIG5hbWVkICoqc3J0bSoqLiBOb3cgd2UgY2FuIHVzZSBgYGBNYXAuYWRkTGF5ZXIoc3J0bSwge21pbjo5MCwgbWF4OjE1MH0sICdERU0nKTtgYGAgdG8gYWRkIERFTSBpbmZvcm1hdGlvbi4gVGhlIG1pbiBhbmQgbWF4IHZhbHVlcyBhcmUgdGhlIGVsZXZhdGlvbiByYW5nZSBpbiBtZXRlcnMuDQoNCiMgVmVnZXRhdGlvbiBBbmFseXNpcw0KDQpPbmUgb2YgdGhlIGJhc2ljIHJlbW90ZSBzZW5zaW5nIGFuYWx5c2VzIGlzIGEgdmVnZXRhdGlvbiBpbmRleCBjYWxsZWQgbm9ybWFsaXplZCBkaWZmZXJuY2UgdmVnZXRhdGlvbiBpbmRleCAoTkRWSSkuIEl0IGlzIGNhbGN1bGF0ZWQgYXMgYSByYXRpb24gYmV0d2VlbiByZWQgYW5kIG5lYXIgaW5mcmFyZWQgYmFuZHMgd2l0aCBhIHJhbmdlIG9mIC0xIHRvIDEuIFdoZXJlIC0xIGlzIGFic2VuY2Ugb2YgdmVnZXRhdGlvbiBhbmQgMSBpcyBoZWFsdGh5IGdyZWVuIHZlZ2V0YXRpb24uIFRoaXMgY2FuIHF1aWNrbHkgYmUgY2FsY3VsYXRlZCB3aXRoIHRoZSBpbmZvcm1hdGlvbiB3ZSBoYXZlIGFscmVhZHkgc2NyaXB0ZWQuDQoNClRvIGJlZ2luIHdlIG5lZWQgdG8gY3JlYXRlIGFuIGVxdWF0aW9uIGFuZCB2YXJpYWJsZXMgZnJvbSB0aGUgU2VudGluZWwgZGF0YS4NCmBgYA0KdmFyIE5EVkkgPSBpbWFnZS5leHByZXNzaW9uKA0KICAiKE5JUiAtIFJFRCkgLyAoTklSICsgUkVEKSIsDQogIHsNCiAgICBSRUQ6IGltYWdlLnNlbGVjdCgiQjQiKSwNCiAgICBOSVI6IGltYWdlLnNlbGVjdCgiQjgiKQ0KICAgIH0pOw0KICANCk1hcC5hZGRMYXllcihORFZJLCB7bWluOiAwLCBtYXg6IDF9LCAiTkRWSSIpOw0KYGBgDQpSZW1lbWJlciB0aGF0IGluIFNlbnRpbmVsLCBCYW5kIDQgaXMgdGhlIFJlZCBiYW5kIGFuZCBCYW5kIDggaXMgTmVhciBJbmZyYXJlZC4gTm93IHdlIGhhdmUgYSBibGFjayBhbmQgd2hpdGUgaW1hZ2Ugc2NhbGVkIHdpdGggTkRWSSB2YWx1ZXMuDQoNCjxwIGFsaWduPSJjZW50ZXIiPg0KDQohW10oLi9JbWFnZXMvTkRWSS5wbmcgIk5EVkkgSW1hZ2UiKQ0KPC9wPg0KDQpJZiB3ZSB3YW50IHRvIGRldGVybWluZSB0aGUgdmFsdWUgb2YgYW4gaW5kaXZpZHVhbCBwaXhlbCwgd2UgY2FuIHVzZSB0aGUgaW5zcGVjdG9yIHRhYiBhbmQgdXNlIHRoZSBjcm9zc2hhaXJzIHRvIGNsaWNrIG9uIGFuIGFyZWEgb2YgaW50ZXJlc3QuIE9uY2UgeW91IHNlbGVjdCBhIGxvY2F0aW9uIGFuZCBsZWZ0LWNsaWNrIHlvdSB3aWxsIHNlZSBhIHNlcmllcyBvZiBncmFwaHMgYXBwZWFyIGluIHRoZSB0YWIuDQoNCjxwIGFsaWduPSJjZW50ZXIiPg0KDQohW10oLi9JbWFnZXMvSW5zcGVjdG9yX1RhYi5wbmcgIlJlc3VsdHMgaW4gdGhlIEluc3BlY3RvciBUYWIiKQ0KPC9wPg0KDQpUaGVzZSBncmFwaHMgZGVwaWN0IHRoZSBwaXhlbCB2YWx1ZXMgb2YgZWFjaCBiYW5kIGluIHRoZSB0d28gaW1hZ2UgdmFyaWFibGVzIGFuZCB0aGUgTkRWSSB2YWx1ZSBvZiAwLjI1MTg5Ny4gQ2xpY2sgYXJvdW5kIHRoZSBpbWFnZSBvbiBkYXJrIGFuZCBsaWdodCBwaXhlbHMgYW5kIGFyZWFzIHdoZXJlIHlvdSB0aGluayB5b3Uga25vdyB0aGUgbGFuZCBjb3ZlciB0byBzZWUgaWYgdGhlIHJlc3VsdHMgbWF0Y2ggeW91ciBpZGVhIG9mIHRoZSBsb2NhdGlvbiAoZm9yZXN0ID0gaGlnaCB2YWx1ZXMsIGxpdHRsZS9ubyB2ZWdldGF0aW9uID0gbG93IHZhbHVlcykuDQoNCiMgWU9VUiBUVVJOIQ0KDQpOb3cgaXQncyB5b3VyIHR1cm4hIEEgbnVtYmVyIG9mIHlvdSBoYWQgaXNzdWVzIG9idGFpbmluZyByZWxpYWJsZSBpbWFnZXJ5IGZvciB5b3VyIHJlc2VhcmNoIGFyZWEgKG9yIGFyZWEgb2YgaW50ZXJlc3QpIGR1ZSB0byBjb21wbGljYXRpb25zIHdpdGggT3BlblN0cmVldE1hcCBvciBub3QgaGF2aW5nIGFuIEFQSS4gVXNpbmcgdGhlIHNjcmlwdCBhYm92ZSwgYWx0ZXIgdGhlIGluZm9ybWF0aW9uIHRvIGZvY3VzIG9uIHlvdXIgdGhlc2lzIG9yIHJlc2VhcmNoIGFyZWEgYW5kIGRvd25sb2FkIGFuIFJHQiBpbWFnZS4gSWYgeW91IGhhdmUgdGltZSwgdHJ5IHRvIGFkZCB0aGF0IGltYWdlIHRvIG9uZSBvZiB5b3VyIHByZXZpb3VzIGV4ZXJjaXNlcyB3aXRob3V0IGFlcmlhbCBpbWFnZXJ5IGFzIGEgYmFzZW1hcC4gVXNpbmcgdGhlICoqZ2V0IGxpbmsqKiBidXR0b24gYXQgdGhlIHRvcCBvZiB0aGUgc2NyaXB0aW5nIHdpbmRvdywgY29weSB0aGUgVVJMLCBhbmQgYWRkIGl0IHRvIHRoZSBSRUFETUUgZG9jdW1lbnQgZm9yIHRoYXQgZXhlcmNpc2UgdG8gcHJvdmlkZSBhY2Nlc3MgdG8gdGhlIHNjcmlwdC4NCg0KIyBSZWZlcmVuY2VzDQpbMV06IEdvcmVsaWNrLCBOLiwgSGFuY2hlciwgTS4sIERpeG9uLCBNLiwgSWx5dXNoY2hlbmtvLCBTLiwgVGhhdSwgRC4sIGFuZCBNb29yZSwgUi4gKDIwMTcpIEdvb2dsZSBFYXJ0aCBFbmdpbmU6IFBsYW5ldGFyeS1zY2FsZSBnZW9zcGF0aWFsIGFuYWx5c2lzIGZvciBldmVyeW9uZS4gUmVtb3RlIFNlbnNpbmcgb2YgRW52aXJvbm1lbnQgMjAyKDEpLiBodHRwczovL2RvaS5vcmcvMTAuMTAxNi9qLnJzZS4yMDE3LjA2LjAzMQ0KDQpBdCB0aGUgR2VvRm9yR29vZCBTdW1taXQgSSBhdHRlbmRlZCB0aGlzIGZhbGwsIHRoZSBwcmVzZW50ZXJzIHdlcmUgZ3JhY2lvdXMgZW5vdWdoIHRvIHByb3ZpZGUgYWNjZXNzIHRvIHRoZWlyIHByZXNlbnRhdGlvbnMuIE1hbnkgb2YgdGhlc2UgaGF2ZSBsaW5rcyB0byBleGFtcGxlIGNvZGUuIEkgYW0gcHJvdmlkaW5nIHRoZW0gaW4gdGhlIHByZXNlbnRhdGlvbnMgZm9sZGVyIG9mIHRoaXMgcmVwb3NpdG9yeS4NCg==